package qc.module.ehs.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.EhsHazardIndentificationResultTypeEnum;
import qc.common.core.enums.EhsRiskLevelEnum;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.common.core.utils.DateUtil;
import qc.common.core.utils.IdentifierUtil;
import qc.module.ehs.dto.hazard.*;
import qc.module.ehs.dto.hazardidentity.HazardIdentifyInfoDto;
import qc.module.ehs.dto.hazardledger.*;
import qc.module.ehs.dto.riskevaluation.HazardRiskEvaluationDto;
import qc.module.ehs.dto.troublecorrect.EhsTroubleCorrectInfoDto;
import qc.module.ehs.dto.unit.EhsUnitSimpleDto;
import qc.module.ehs.dto.unit.EhsUnitTreeSimpleDto;
import qc.module.ehs.entity.*;
import qc.module.ehs.mapper.*;
import qc.module.ehs.repository.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 危险源信息Service
 *
 * @author QuCheng Tech
 * @create 2024/11/5
 */
@Service
public class EhsHazardInfoService {

    @Autowired
    private EhsHazardInfoRepository repository;

    @Autowired
    private EhsHazardIdentifyRepository identifyRepository;

    @Autowired
    private EhsHazardRiskevlRepository riskevlRepository;

    @Autowired
    private EhsUnitInfoRepository unitInfoRepository;

    @Autowired
    private EhsTroubleCorrectRepository troubleCorrectRepository;

    /**
     * 获取指定危险源信息
     *
     * @param id 危险源ID
     * @return EhsHazardBasicDto
     * @author QuCheng Tech
     * @since 2024/7/3
     */
    public EhsHazardInfoDto get(String id) {
        EhsHazardInfo en = repository.selectById(id);

        if (Objects.nonNull(en)) {
            return EhsHazardInfoMapper.MAPPER.toDto(en);
        }
        return null;
    }

    /**
     * 获取指定危险源完整信息
     *
     * @param id 危险源ID
     * @return EhsHazardFullInfoDto
     * @author QuCheng Tech
     * @since 2024/11/5
     */
    public EhsHazardFullInfoDto getFullInfo(String id) {

        //返回结果
        EhsHazardFullInfoDto result = new EhsHazardFullInfoDto();

        //1.获取指定危险源信息
        EhsHazardInfo hazardInfo = repository.selectById(id);
        if (Objects.isNull(hazardInfo)) return result;

        //2.定义返回结果项
        EhsHazardInfoDto info = EhsHazardInfoMapper.MAPPER.toDto(hazardInfo);
        List<HazardIdentifyInfoDto> identifications = new ArrayList<>();
        List<HazardRiskEvaluationDto> evaluations = new ArrayList<>();
        List<EhsTroubleCorrectInfoDto> corrects = new ArrayList<>();

        //3.获取指定危险源的辨识记录(按辨识时间降序)
        LambdaQueryWrapper<EhsHazardIdentify> identifyWrapper = new LambdaQueryWrapper<>();
        identifyWrapper.eq(EhsHazardIdentify::getHazardid, id).orderByDesc(EhsHazardIdentify::getTm);
        List<EhsHazardIdentify> identifies = identifyRepository.selectList(identifyWrapper);
        if (CollectionUtils.isNotEmpty(identifies)) {
            for (EhsHazardIdentify en : identifies) {
                identifications.add(EhsHazardIdentifyMapper.MAPPER.entityToDto(en));
            }
        }

        //4.获取指定危险源的风险评价记录(按风险评价时间降序)
        LambdaQueryWrapper<EhsHazardRiskEvaluation> riskevlWrapper = new LambdaQueryWrapper<>();
        riskevlWrapper.eq(EhsHazardRiskEvaluation::getHazardid, id).orderByDesc(EhsHazardRiskEvaluation::getTm);
        List<EhsHazardRiskEvaluation> riskevls = riskevlRepository.selectList(riskevlWrapper);
        if (CollectionUtils.isNotEmpty(riskevls)) {
            evaluations = EhsHazardRiskEvaluationMapper.MAPPER.toDtoList(riskevls);
        }

        //5.获取指定隐患治理集合
        LambdaQueryWrapper<EhsTroubleCorrect> correctWrapper = new LambdaQueryWrapper<>();
        correctWrapper.eq(EhsTroubleCorrect::getHazardid, id);
        List<EhsTroubleCorrect> troubleCorrects = troubleCorrectRepository.selectList(correctWrapper);
        if (CollectionUtils.isNotEmpty(troubleCorrects)) {
            corrects = EhsTroubleCorrectMapper.MAPPER.toDtoList(troubleCorrects);
        }

        //6.设置结果项并返回
        result.setInfo(info);
        result.setIdentifications(identifications);
        result.setEvaluations(evaluations);
        result.setCorrects(corrects);
        return result;
    }

    /**
     * 获取指定单元的危险源集合
     * 用于在危险源辨识记录确认时提供给确认对应的危险源下拉列表使用；
     * 如果有传入类别、项目和清单直接进行匹配；
     *
     * @param condition 查询条件
     * @return List<EhsHazardInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/13
     */
    public List<EhsHazardInfoDto> queryUnitHazards(EhsHazardUnitQueryConditionDto condition) throws QCPromptException {
        //1.查询条件有效性验证
        if (condition == null) throw new QCPromptException("查询条件不能为空");
        if (StringUtils.isBlank(condition.getUnitid())) throw new QCPromptException("单元ID不能为空");

        //2.构建查询条件
        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsHazardInfo::getUnitid, condition.getUnitid());
        if (StringUtils.isNotBlank(condition.getCategorycode())) {
            wrapper.eq(EhsHazardInfo::getCategorycode, condition.getCategorycode());
        }
        if (StringUtils.isNotBlank(condition.getProjectcode())) {
            wrapper.eq(EhsHazardInfo::getProjectcode, condition.getProjectcode());
        }
        if (StringUtils.isNotBlank(condition.getItemcode())) {
            wrapper.eq(EhsHazardInfo::getItemcode, condition.getItemcode());
        }

        //3.查询危险源
        List<EhsHazardInfo> ens = repository.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(ens)) {
            return EhsHazardInfoMapper.MAPPER.toDtoList(ens);
        }
        return null;
    }

    /**
     * 获取指定单元的危险源信息集合
     *
     * @param unitid 指定单元ID
     * @return List<EhsHazardInfo>
     */
    public List<EhsHazardInfoDto> getByUnitId(String unitid) {
        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsHazardInfo::getUnitid, unitid);
        List<EhsHazardInfo> ens = repository.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(ens)) {
            return EhsHazardInfoMapper.MAPPER.toDtoList(ens);
        }
        return null;
    }

    /**
     * 新增危险源信息
     *
     * @param dto 新增对象
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/6
     */
    public String add(EhsHazardInfoDto dto) throws QCPromptException {
        if (dto == null) return QCUnifyReturnValue.Warn("新增对象不能为空");
        if (StringUtils.isBlank(dto.getOrgcode())) return QCUnifyReturnValue.Warn("所属组织代码不能为空");
        if (StringUtils.isBlank(dto.getHazardname())) return QCUnifyReturnValue.Warn("危险源名称不能为空");
        if (StringUtils.isBlank(dto.getUnitid())) return QCUnifyReturnValue.Warn("所属单元ID不能为空");
        if (StringUtils.isBlank(dto.getTitle())) return QCUnifyReturnValue.Warn("标题不能为空");

        //最近辨识时间格式转换处理
        Date identificationTm = null;
        if (StringUtils.isNotBlank(dto.getRecentidentificationtm())) {
            try {
                identificationTm = DateUtil.parseDate(dto.getRecentidentificationtm());
            } catch (Exception e) {
                // 时间转换错误，抛出自定义异常
                throw new QCPromptException("最近辨识时间日期转换错误");
            }
            dto.setRecentidentificationtm(null);
        }

        //dto转entity
        EhsHazardInfo en = EhsHazardInfoMapper.MAPPER.dtoToEntity(dto);
        if (StringUtils.isBlank(dto.getHazardid())) {
            en.setHazardid(IdentifierUtil.randomUUID());
        }
        en.setRecentidentificationtm(identificationTm);

        if (repository.insert(en) < 0x1) {
            return QCUnifyReturnValue.Warn("保存失败");
        }
        return QCUnifyReturnValue.Success();
    }

    /**
     * 修改危险源信息
     *
     * @param dto 修改对象
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/6
     */
    public String update(EhsHazardInfoDto dto) throws QCPromptException {
        if (dto == null) return QCUnifyReturnValue.Warn("对象不能为空");
        if (StringUtils.isBlank(dto.getHazardid())) return QCUnifyReturnValue.Warn("危险源ID不能为空");
        if (StringUtils.isBlank(dto.getOrgcode())) return QCUnifyReturnValue.Warn("所属组织代码不能为空");
        if (StringUtils.isBlank(dto.getHazardname())) return QCUnifyReturnValue.Warn("危险源名称不能为空");
        if (StringUtils.isBlank(dto.getUnitid())) return QCUnifyReturnValue.Warn("所属单元ID不能为空");
        if (StringUtils.isBlank(dto.getTitle())) return QCUnifyReturnValue.Warn("标题不能为空");

        //最近辨识时间格式转换处理
        Date identificationTm = null;
        if (StringUtils.isNotBlank(dto.getRecentidentificationtm())) {
            try {
                identificationTm = DateUtil.parseDate(dto.getRecentidentificationtm());
            } catch (Exception e) {
                // 时间转换错误，抛出自定义异常
                throw new QCPromptException("最近辨识时间日期转换错误");
            }
            dto.setRecentidentificationtm(null);
        }

        //dto转entity
        EhsHazardInfo en = EhsHazardInfoMapper.MAPPER.dtoToEntity(dto);
        en.setRecentidentificationtm(identificationTm);

        repository.updateById(en);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 根据单元ID集合获取危险源信息
     *
     * @param unitIds 单元ID集合
     * @return List<EhsHazardBasicDto>
     * @throws QCPromptException
     * @author QuCheng Tech
     * @since 2024/7/17
     */
    public List<EhsHazardInfoDto> getHazardsByUnitIds(List<String> unitIds) throws QCPromptException {
        if (CollectionUtils.isEmpty(unitIds)) throw new QCPromptException("单元ID集合不能为空");
        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(EhsHazardInfo::getUnitid, unitIds);
        List<EhsHazardInfo> ens = repository.selectList(wrapper);

        if (ens != null && ens.size() > 0x0) {
            return EhsHazardInfoMapper.MAPPER.toDtoList(ens);
        }
        return null;
    }

    /**
     * 查询危险源台账
     *
     * @param condition 查询条件
     * @param deptIds   当前用户所属部门ID集合
     * @return HazardLedgerQueryResultDto
     * @author QuCheng Tech
     * @description 按危险源清单/台账查询危险源信息；显示查询结果中的危险源统计信息：一般危险源数量、重大危险源数量、第一类、第二类危险源数量、各风险等级危险源数量，可以在表格上显示汇总行。
     * 查询结果只返回辨识结果存在的危险源。
     * @since 2024/11/6
     */
    public HazardLedgerQueryResultDto query(HazardLedgerQueryConditionDto condition, List<Integer> deptIds) throws QCPromptException {
        if (condition == null)
            throw new QCPromptException("查询条件不能为空");
        if (StringUtils.isBlank(condition.getOrgcode()))
            throw new QCPromptException("组织代码不能为空");

        //1.定义返回结果
        HazardLedgerQueryResultDto result = new HazardLedgerQueryResultDto();
        HazardAccountResultDto items = new HazardAccountResultDto();
        int general1 = 0x0, major1 = 0x0, level11 = 0x0, level12 = 0x0, level13 = 0x0, level14 = 0x0,
                general2 = 0x0, major2 = 0x0, level21 = 0x0, level22 = 0x0, level23 = 0x0, level24 = 0x0;

        //2.查询指定条件的单元信息，如果查询指定单元（该单元作为一级单元，返回子级）,否则查询所有
        List<EhsUnitInfo> unitInfos = new ArrayList<>();
        LambdaQueryWrapper<EhsUnitInfo> unitWrapper = new LambdaQueryWrapper<>();
        unitWrapper.eq(EhsUnitInfo::getOrgcode, condition.getOrgcode());
        //查询指定单元
        if (StringUtils.isNotBlank(condition.getUnitid())) {
            unitWrapper.eq(EhsUnitInfo::getUnitid, condition.getUnitid());
            EhsUnitInfo unitInfo = unitInfoRepository.selectOne(unitWrapper);
            unitInfos.add(unitInfo);
            //查询单元的子级单元
            LambdaQueryWrapper<EhsUnitInfo> subUnitWrapper = new LambdaQueryWrapper<>();
            subUnitWrapper.ne(EhsUnitInfo::getUnitid, unitInfo.getUnitid())
                    .likeRight(EhsUnitInfo::getLevelcode, unitInfo.getLevelcode())
                    .orderByAsc(EhsUnitInfo::getOdr, EhsUnitInfo::getUnitname);//根据单元的层级编码开头去查询子级
            List<EhsUnitInfo> subUniInfos = unitInfoRepository.selectList(subUnitWrapper);
            if (CollectionUtils.isNotEmpty(subUniInfos)) unitInfos.addAll(subUniInfos);
        } else {
            unitWrapper.orderByAsc(EhsUnitInfo::getOdr, EhsUnitInfo::getUnitname);
            unitInfos = unitInfoRepository.selectList(unitWrapper);
        }
        if (CollectionUtils.isEmpty(unitInfos)) return null;

        //3.将单元信息构建为树型结构，根据条件过滤单元信息
        List<String> unitIds = new ArrayList<>();//树结构中筛选后的单元ID集合
        List<EhsUnitTreeSimpleDto> units = new ArrayList<>();
        //转换为dtoSimpleList
        List<EhsUnitSimpleDto> unitSimpleDtos = EhsUnitInfoMapper.MAPPER.toDtoSimpleList(unitInfos);
        //获取根节点集合（如果查询指定单元，将指定单元作为根层级单元，否则parentid为空的作为根层级单元）
        List<EhsUnitSimpleDto> rootUnits = new ArrayList<>();
        if (StringUtils.isNotBlank(condition.getUnitid())) {
            rootUnits = unitSimpleDtos.stream().
                    filter(p -> p.getUnitid().equals(condition.getUnitid())).collect(Collectors.toList());
        } else {
            rootUnits = unitSimpleDtos.stream().filter(p -> StringUtils.isEmpty(p.getParentid())).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(rootUnits)) {
            for (EhsUnitSimpleDto rootUnit : rootUnits) {
                EhsUnitTreeSimpleDto unitTreeSimpleDto = new EhsUnitTreeSimpleDto();
                List<EhsUnitTreeSimpleDto> children = new ArrayList<>();
                unitTreeSimpleDto.setInfo(rootUnit);
                unitTreeSimpleDto.setChildren(children);
                //查询条件中要获取子级单元为true时，获取子级单元集合
                if (condition.isIncludechilds() == true)
                    getSubUnitsSimple(unitSimpleDtos, rootUnit, children, unitIds);
                units.add(unitTreeSimpleDto);
                unitIds.add(rootUnit.getUnitid());
            }
        }

        //4.根据查询条件筛选单元信息
        List<String> removedUnitIds = new ArrayList<>();//被筛选移除的单元ID
        Iterator<EhsUnitTreeSimpleDto> rootLevelIterator = units.iterator();
        while (rootLevelIterator.hasNext()) {
            EhsUnitTreeSimpleDto rootlevel = rootLevelIterator.next();
            if (rootlevel.getChildren() != null && rootlevel.getChildren().size() > 0x0) {
                //子级结果筛选
                filterSubTreeSimpleResult(rootlevel, condition, deptIds, removedUnitIds);
            }

            //是否移除
            boolean isRemoveRootLevel = false;

            //判断是否包含子级，不包含则设置子级为空
            if (condition.isIncludechilds() == false)
                rootlevel.setChildren(null);

            //匹配当前层级
            if (rootlevel.getChildren() == null || rootlevel.getChildren().size() == 0x0) {
                //是否为在建工程：为0表示false，为1表示true，为空或其他时表示不管该标记状态
                if (StringUtils.isNotBlank(condition.getIsconstruction())) {
                    if (condition.getIsconstruction().equals("0") || condition.getIsconstruction().equals("false")) {
                        if (rootlevel.getInfo().isIsconstruction() == true) isRemoveRootLevel = true;
                    } else if (condition.getIsconstruction().equals("1") || condition.getIsconstruction().equals("true")) {
                        if (rootlevel.getInfo().isIsconstruction() == false) isRemoveRootLevel = true;
                    }
                }
                //是否根据用户部门进行过滤:为true表示根据当前用户所关联部门对单元进行筛选过滤，为false表示不过滤
                if (condition.isIsdept() == true) {
                    if (CollectionUtils.isNotEmpty(deptIds)) {
                        boolean deptIsExist = false;//level4的部门是否匹配用户部门
                        for (Integer deptId : deptIds) {
                            if (deptId == rootlevel.getInfo().getResdeptid()) {
                                deptIsExist = true;
                            }
                        }
                        if (!deptIsExist) isRemoveRootLevel = true;
                    }
                }
                if (isRemoveRootLevel) {
                    removedUnitIds.add(rootlevel.getInfo().getUnitid());
                    rootLevelIterator.remove();
                }
            }
        }
        items.setUnits(units);

        //5.查询过滤后的单元的危险源信息集合（只查询辨识结果存在的），根据查询条件过滤危险源信息
        //从所有的单元id中过滤掉被移除的单元ID
        unitIds.removeAll(removedUnitIds);
        if (CollectionUtils.isNotEmpty(unitIds)) {
            LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(EhsHazardInfo::getUnitid, unitIds);
            wrapper.ne(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.NOT_EXIST.getIndex());
            //匹配危险源级别：为0表示false(一般)，为1表示true(重大)，为空或其他时表示不管该标记状态
            if (StringUtils.isNotBlank(condition.getIsmajor())) {
                if (condition.getIsmajor().equals("0") || condition.getIsmajor().equals("false"))
                    wrapper.eq(EhsHazardInfo::getIsmajor, false);
                else if (condition.getIsmajor().equals("1") || condition.getIsmajor().equals("true"))
                    wrapper.eq(EhsHazardInfo::getIsmajor, true);
            }
            //匹配危险源类别：为0表示false(第一类危险源)，为1表示true(第二类危险源)，为空或其他时表示不管该标记状态;
            if (StringUtils.isNotBlank(condition.getIshidden())) {
                if (condition.getIshidden().equals("0") || condition.getIshidden().equals("false"))
                    wrapper.eq(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.HAZARD.getIndex());
                else if (condition.getIshidden().equals("1") || condition.getIshidden().equals("true"))
                    wrapper.eq(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.HIDDEN_TROUBLE.getIndex());
            }
            //匹配危险源风险等级
            if (StringUtils.isNotBlank(condition.getRisklevel()))
                wrapper.eq(EhsHazardInfo::getRisklevel, Integer.parseInt(condition.getRisklevel()));
            //关键字匹配，可以是危险源类别、项目、危险源名称、标题
            if (StringUtils.isNotBlank(condition.getKeywords())) {
                wrapper.and(q -> q.like(EhsHazardInfo::getCategoryname, condition.getKeywords()).or()
                                .like(EhsHazardInfo::getProjectname, condition.getKeywords()).or()
                                .like(EhsHazardInfo::getHazardname, condition.getKeywords())).or()
                        .like(EhsHazardInfo::getTitle, condition.getKeywords());
            }
            //危险源信息排序：按照危险源类别、项目、名称升序
            wrapper.orderByAsc(EhsHazardInfo::getCategoryname, EhsHazardInfo::getProjectname, EhsHazardInfo::getHazardname);
            List<EhsHazardInfo> hazardInfos = repository.selectList(wrapper);
            if (hazardInfos != null && hazardInfos.size() > 0x0) {
                List<EhsHazardInfoDto> hazards = EhsHazardInfoMapper.MAPPER.toDtoList(hazardInfos);
                items.setHazards(hazards);

                //5.将危险源信息中的类别、项目、危险源处理为层级关系的树型结构
                List<HazardCategoryTreeDto> categoryDtos = new ArrayList<>();
                List<HazardCategoryTreeDto> projectDtos = new ArrayList<>();
                List<HazardCategoryTreeDto> hazardDtos = new ArrayList<>();
                for (EhsHazardInfoDto hazard : hazards) {
                    HazardCategoryTreeDto categoryDto = new HazardCategoryTreeDto();
                    categoryDto.setCode(hazard.getCategorycode());
                    categoryDto.setName(hazard.getCategoryname());
                    categoryDto.setLevel(1);
                    categoryDtos.add(categoryDto);

                    HazardCategoryTreeDto projectDto = new HazardCategoryTreeDto();
                    projectDto.setCode(hazard.getProjectcode());
                    projectDto.setName(hazard.getProjectname());
                    projectDto.setParentCode(hazard.getCategorycode());
                    projectDto.setLevel(2);
                    projectDtos.add(projectDto);

                    HazardCategoryTreeDto hazardDto = new HazardCategoryTreeDto();
                    hazardDto.setCode(hazard.getHazardid());
                    hazardDto.setName(hazard.getHazardname());
                    hazardDto.setParentCode(hazard.getProjectcode());
                    hazardDto.setLevel(3);
                    hazardDtos.add(hazardDto);

                    //危险源各类/各风险等级数量统计
                    if (hazard.getIdentificationresult() == EhsHazardIndentificationResultTypeEnum.HAZARD.getIndex()) {
                        //第一类危险源
                        if (hazard.isIsmajor()) major1 += 0x1;
                        else general1 += 0x1;
                        if (hazard.getRisklevel() == EhsRiskLevelEnum.LOW.getIndex()) level11 += 0x1;
                        else if (hazard.getRisklevel() == EhsRiskLevelEnum.GENERAL.getIndex()) level12 += 0x1;
                        else if (hazard.getRisklevel() == EhsRiskLevelEnum.GREATER.getIndex()) level13 += 0x1;
                        else if (hazard.getRisklevel() == EhsRiskLevelEnum.MAJOR.getIndex()) level14 += 0x1;
                    } else if (hazard.getIdentificationresult() == EhsHazardIndentificationResultTypeEnum.HIDDEN_TROUBLE.getIndex()) {
                        //第二类危险源
                        if (hazard.isIsmajor()) major2 += 0x1;
                        else general2 += 0x1;
                        if (hazard.getRisklevel() == EhsRiskLevelEnum.LOW.getIndex()) level21 += 0x1;
                        else if (hazard.getRisklevel() == EhsRiskLevelEnum.GENERAL.getIndex()) level22 += 0x1;
                        else if (hazard.getRisklevel() == EhsRiskLevelEnum.GREATER.getIndex()) level23 += 0x1;
                        else if (hazard.getRisklevel() == EhsRiskLevelEnum.MAJOR.getIndex()) level24 += 0x1;
                    }
                }
                //危险源类别、项目信息去重
                List<HazardCategoryTreeDto> categorys = categoryDtos.stream().distinct().collect(Collectors.toList());
                List<HazardCategoryTreeDto> projects = projectDtos.stream().distinct().collect(Collectors.toList());
                for (HazardCategoryTreeDto category : categorys) {
                    List<HazardCategoryTreeDto> categoryChildren = new ArrayList<>();
                    for (HazardCategoryTreeDto project : projects) {
                        List<HazardCategoryTreeDto> projectChildren = new ArrayList<>();
                        for (HazardCategoryTreeDto hazard : hazardDtos) {
                            if (hazard.getParentCode().equals(project.getCode())) {
                                projectChildren.add(hazard);
                            }
                        }
                        project.setChildren(projectChildren);
                        if (project.getParentCode().equals(category.getCode())) {
                            categoryChildren.add(project);
                        }
                    }
                    category.setChildren(categoryChildren);
                }
                items.setCategorys(categorys);
                result.setItems(items);
            }
        }

        //设置危险源数量
        result.setGeneral1(general1);
        result.setMajor1(major1);
        result.setLevel11(level11);
        result.setLevel12(level12);
        result.setLevel13(level13);
        result.setLevel14(level14);
        result.setGeneral2(general2);
        result.setMajor2(major2);
        result.setLevel21(level21);
        result.setLevel22(level22);
        result.setLevel23(level23);
        result.setLevel24(level24);
        return result;
    }

    /**
     * 拼接父级单元的子孙层级结构
     *
     * @param dtos         所有单元信息
     * @param parentUnit   父级单元
     * @param parentChilds 父级单元的子孙集合
     * @param unitIds      单元ID集合
     * @author QuCheng Tech
     * @since 2024/5/31
     */
    public void getSubUnitsSimple(List<EhsUnitSimpleDto> dtos, EhsUnitSimpleDto parentUnit,
                                  List<EhsUnitTreeSimpleDto> parentChilds, List<String> unitIds) {
        List<EhsUnitSimpleDto> subUnits = dtos.stream().filter(p -> p.getParentid() != null &&
                p.getParentid().equals(parentUnit.getUnitid())).collect(Collectors.toList());
        for (EhsUnitSimpleDto subUnit : subUnits) {
            EhsUnitTreeSimpleDto unitTreeSimpleDto = new EhsUnitTreeSimpleDto();
            List<EhsUnitTreeSimpleDto> children = new ArrayList<>();
            unitTreeSimpleDto.setInfo(subUnit);
            unitTreeSimpleDto.setChildren(children);

            parentChilds.add(unitTreeSimpleDto);

            unitIds.add(subUnit.getUnitid());

            getSubUnitsSimple(dtos, subUnit, children, unitIds);
        }
    }

    /**
     * 递归过滤单元TreeSimple的子级结果
     *
     * @param rootLevel 父层级单元
     * @param condition 过滤条件
     * @param deptIds   当前用户所属部门集合
     * @author QuCheng Tech
     * @since 2024/5/31
     */
    private void filterSubTreeSimpleResult(EhsUnitTreeSimpleDto rootLevel, HazardLedgerQueryConditionDto condition,
                                           List<Integer> deptIds, List<String> removedUnitIds) {
        Iterator<EhsUnitTreeSimpleDto> subLevelIterator = rootLevel.getChildren().iterator();
        while (subLevelIterator.hasNext()) {
            EhsUnitTreeSimpleDto subLevel = subLevelIterator.next();

            if (subLevel.getChildren() != null && subLevel.getChildren().size() > 0x0) {
                filterSubTreeSimpleResult(subLevel, condition, deptIds, removedUnitIds);
            }

            //判断是否包含子级，不包含则设置子级为空
            if (condition.isIncludechilds() == false)
                subLevel.setChildren(null);

            //筛选当前层级
            if (subLevel.getChildren() == null || subLevel.getChildren().size() == 0x0) {
                //是否移除
                boolean isRemoveSubLevel = false;
                //是否为在建工程：为0表示false，为1表示true，为空或其他时表示不管该标记状态
                if (StringUtils.isNotBlank(condition.getIsconstruction())) {
                    if (condition.getIsconstruction().equals("0") || condition.getIsconstruction().equals("false")) {
                        if (subLevel.getInfo().isIsconstruction() == true) isRemoveSubLevel = true;
                    } else if (condition.getIsconstruction().equals("1") || condition.getIsconstruction().equals("true")) {
                        if (subLevel.getInfo().isIsconstruction() == false) isRemoveSubLevel = true;
                    }
                }
                //是否根据用户部门进行过滤:为true表示根据当前用户所关联部门对单元进行筛选过滤，为false表示不过滤
                if (condition.isIsdept() == true) {
                    if (CollectionUtils.isNotEmpty(deptIds)) {
                        boolean deptIsExist = false;//level4的部门是否匹配用户部门
                        for (Integer deptId : deptIds) {
                            if (deptId == subLevel.getInfo().getResdeptid()) {
                                deptIsExist = true;
                            }
                        }
                        if (!deptIsExist) isRemoveSubLevel = true;
                    }
                }
                if (isRemoveSubLevel) {
                    removedUnitIds.add(subLevel.getInfo().getUnitid());
                    subLevelIterator.remove();
                }
            }

        }
    }

    /**
     * 按单元查询危险源
     *
     * @param condition 查询条件
     * @param deptIds   当前用户所属部门ID集合
     * @return QueryHazardByUnitResultDto
     * @author QuCheng Tech
     * @description 表格数据说明：返回用户所在组织中的所有独立场所/区域单元（需判断台账模式还是辨识评价模式），需要处理查询条件中的单元下拉选择条件；
     * 返回结果中不管是否有对应单元辨识记录，均返回单元名称信息，其他列信息保持为空；
     * 单元有层级关系，按层级关系显示。上级单元与子级单元的危险源数量之间不做关联。
     * 台账模式下只能进行查询和数据显示，辨识评价模式下才能进行操作。辨识评价模式单元需要根据用户部门进行过滤。
     * @since 2024/11/6
     */
    public QueryHazardByUnitResultDto queryByUnit(
            QueryHazardByUnitConditionDto condition, List<Integer> deptIds) throws QCPromptException {
        //1.查询条件有效性验证
        if (condition == null) throw new QCPromptException("查询条件不能为空");
        if (StringUtils.isBlank(condition.getOrgcode())) throw new QCPromptException("组织代码不能为空");

        //2.查询指定条件的单元信息，如果查询指定单元（该单元作为一级单元，返回子级）,否则查询所有
        List<EhsUnitInfo> unitInfos = new ArrayList<>();
        LambdaQueryWrapper<EhsUnitInfo> unitWrapper = new LambdaQueryWrapper<>();
        unitWrapper.eq(EhsUnitInfo::getOrgcode, condition.getOrgcode());
        //查询指定单元
        if (StringUtils.isNotBlank(condition.getUnitid())) {
            unitWrapper.eq(EhsUnitInfo::getUnitid, condition.getUnitid());
            EhsUnitInfo unitInfo = unitInfoRepository.selectOne(unitWrapper);
            unitInfos.add(unitInfo);
            //查询单元的子级单元
            LambdaQueryWrapper<EhsUnitInfo> subUnitWrapper = new LambdaQueryWrapper<>();
            subUnitWrapper.ne(EhsUnitInfo::getUnitid, unitInfo.getUnitid())
                    .likeRight(EhsUnitInfo::getLevelcode, unitInfo.getLevelcode());//根据单元的层级编码开头去查询子级
            List<EhsUnitInfo> subUniInfos = unitInfoRepository.selectList(subUnitWrapper);
            if (CollectionUtils.isNotEmpty(subUniInfos)) unitInfos.addAll(subUniInfos);
        } else {
            unitInfos = unitInfoRepository.selectList(unitWrapper);
        }
        if (CollectionUtils.isEmpty(unitInfos)) return null;

        //3.unitInfos转换为QueryHazardByUnitResultItemDtos，获取单元ID集合
        List<QueryHazardByUnitResultItemDto> resultItemDtos = EhsUnitInfoMapper.MAPPER.toHazardByUnitResultItemTreeDtoList(unitInfos);

        //4.将危险源结果项resultItemDtos构建为树型结构items
        List<QueryHazardByUnitResultItemDto> items = new ArrayList<>();
        //获取根节点集合（如果查询指定单元，将指定单元作为根层级单元，否则parentid为空的作为根层级单元）
        List<QueryHazardByUnitResultItemDto> rootItems = new ArrayList<>();
        if (StringUtils.isNotBlank(condition.getUnitid())) {
            rootItems = resultItemDtos.stream().
                    filter(p -> p.getUnitid().equals(condition.getUnitid())).collect(Collectors.toList());
        } else {
            rootItems = resultItemDtos.stream().
                    filter(p -> StringUtils.isEmpty(p.getParentid())).collect(Collectors.toList());
        }
        //构建树型结构，设置根单元的子节点单元
        if (CollectionUtils.isNotEmpty(rootItems))
            items = getSubItems(resultItemDtos, rootItems);

        //5.从items中过滤符合查询条件“是否为在建工程、是否根据用户部门进行过滤”的结果项
        Iterator<QueryHazardByUnitResultItemDto> rootLevelIterator = items.iterator();
        while (rootLevelIterator.hasNext()) {
            QueryHazardByUnitResultItemDto rootlevel = rootLevelIterator.next();

            //子级结果筛选
            if (rootlevel.getChildren() != null && rootlevel.getChildren().size() > 0x0) {
                filterSubTreeTableResult(rootlevel, condition, deptIds);
            }
            //当前层级筛选
            //是否移除
            boolean isRemoveRootLevel = false;
            if (rootlevel.getChildren() == null || rootlevel.getChildren().size() == 0x0) {
                //是否为在建工程：为0表示false，为1表示true，为空或其他时表示不管该标记状态
                if (StringUtils.isNotBlank(condition.getIsconstruction())) {
                    if (condition.getIsconstruction().equals("0") || condition.getIsconstruction().equals("false")) {
                        if (rootlevel.isIsconstruction() == true) isRemoveRootLevel = true;
                    } else if (condition.getIsconstruction().equals("1") || condition.getIsconstruction().equals("true")) {
                        if (rootlevel.isIsconstruction() == false) isRemoveRootLevel = true;
                    }
                }
                //是否根据用户部门进行过滤:为true表示根据当前用户所关联部门对单元进行筛选过滤，为false表示不过滤
                if (condition.isIsdept() == true) {
                    if (CollectionUtils.isNotEmpty(deptIds)) {
                        boolean deptIsExist = false;//level4的部门是否匹配用户部门
                        for (Integer deptId : deptIds) {
                            if (deptId == rootlevel.getDeptid()) {
                                deptIsExist = true;
                            }
                        }
                        if (!deptIsExist) isRemoveRootLevel = true;
                    }
                }

                if (isRemoveRootLevel) rootLevelIterator.remove();
            }
        }

        //6.结果统计中各统计值记录：只统计第一层级单元（每个层级都包含子层级单元的危险源数量）
        Integer general1 = 0x0, major1 = 0x0, level11 = 0x0, level12 = 0x0, level13 = 0x0, level14 = 0x0,
                general2 = 0x0, major2 = 0x0, level21 = 0x0, level22 = 0x0, level23 = 0x0, level24 = 0x0;
        for (QueryHazardByUnitResultItemDto itemDto : items) {
            //计算根节点各数量合计值
            general1 += itemDto.getGeneral1();
            major1 += itemDto.getMajor1();
            level11 += itemDto.getLevel11();
            level12 += itemDto.getLevel12();
            level13 += itemDto.getLevel13();
            level14 += itemDto.getLevel14();
            general2 += itemDto.getGeneral2();
            major2 += itemDto.getMajor2();
            level21 += itemDto.getLevel21();
            level22 += itemDto.getLevel22();
            level23 += itemDto.getLevel23();
            level24 += itemDto.getLevel24();
        }

        //7.设置返回结果
        QueryHazardByUnitResultDto result = new QueryHazardByUnitResultDto();
        result.setItems(items);
        result.setGeneral1(general1);
        result.setMajor1(major1);
        result.setLevel11(level11);
        result.setLevel12(level12);
        result.setLevel13(level13);
        result.setLevel14(level14);
        result.setGeneral2(general2);
        result.setMajor2(major2);
        result.setLevel21(level21);
        result.setLevel22(level22);
        result.setLevel23(level23);
        result.setLevel24(level24);
        return result;
    }

    /**
     * 递归获取子级单元危险源信息
     *
     * @param resultItemDtos 所有单元危险源信息
     * @param parentItems    父级单元危险源信息
     * @return List<QueryHazardByUnitResultItemDto>
     * @author QuCheng Tech
     * @since 2024/6/14
     */
    private List<QueryHazardByUnitResultItemDto> getSubItems(List<QueryHazardByUnitResultItemDto> resultItemDtos,
                                                             List<QueryHazardByUnitResultItemDto> parentItems) {
        List<QueryHazardByUnitResultItemDto> items = new ArrayList<>();

        if (CollectionUtils.isEmpty(resultItemDtos)) return null;

        if (CollectionUtils.isNotEmpty(parentItems)) {
            for (QueryHazardByUnitResultItemDto pItem : parentItems) {
                //获取子级单元信息集合
                List<QueryHazardByUnitResultItemDto> subItems = resultItemDtos.stream().filter(p ->
                        pItem.getUnitid().equals(p.getParentid())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(subItems)) {
                    getSubItems(resultItemDtos, subItems);
                    pItem.setChildren(subItems);
                }

                //统计数量为空的设置返回0
                //if (pItem.getGeneral1() == null) pItem.setGeneral1(0x0);
                //if (pItem.getMajor1() == null) pItem.setMajor1(0x0);
                //if (pItem.getLevel11() == null) pItem.setLevel11(0x0);
                //if (pItem.getLevel12() == null) pItem.setLevel12(0x0);
                //if (pItem.getLevel13() == null) pItem.setLevel13(0x0);
                //if (pItem.getLevel14() == null) pItem.setLevel14(0x0);
                //if (pItem.getGeneral2() == null) pItem.setGeneral2(0x0);
                //if (pItem.getMajor2() == null) pItem.setMajor2(0x0);
                //if (pItem.getLevel21() == null) pItem.setLevel21(0x0);
                //if (pItem.getLevel22() == null) pItem.setLevel22(0x0);
                //if (pItem.getLevel23() == null) pItem.setLevel23(0x0);
                //if (pItem.getLevel24() == null) pItem.setLevel24(0x0);

                items.add(pItem);
            }
        }
        return items;
    }

    /**
     * 递归过滤单元危险源结果项的子级结果
     *
     * @param rootLevel 父层级单元危险源结果项
     * @param condition 过滤条件
     * @param deptIds   当前用户所属部门集合
     * @author QuCheng Tech
     * @since 2024/6/14
     */
    private void filterSubTreeTableResult(QueryHazardByUnitResultItemDto rootLevel,
                                          QueryHazardByUnitConditionDto condition, List<Integer> deptIds) {
        Iterator<QueryHazardByUnitResultItemDto> subLevelIterator = rootLevel.getChildren().iterator();
        while (subLevelIterator.hasNext()) {
            QueryHazardByUnitResultItemDto subLevel = subLevelIterator.next();

            if (subLevel.getChildren() != null && subLevel.getChildren().size() > 0x0) {
                filterSubTreeTableResult(subLevel, condition, deptIds);
            }

            if (subLevel.getChildren() == null || subLevel.getChildren().size() == 0x0) {
                //是否移除
                boolean isRemoveSubLevel = false;
                //是否为在建工程：为0表示false，为1表示true，为空或其他时表示不管该标记状态
                if (StringUtils.isNotBlank(condition.getIsconstruction())) {
                    if (condition.getIsconstruction().equals("0") || condition.getIsconstruction().equals("false")) {
                        if (subLevel.isIsconstruction() == true) isRemoveSubLevel = true;
                    } else if (condition.getIsconstruction().equals("1") || condition.getIsconstruction().equals("true")) {
                        if (subLevel.isIsconstruction() == false) isRemoveSubLevel = true;
                    }
                }
                //是否根据用户部门进行过滤:为true表示根据当前用户所关联部门对单元进行筛选过滤，为false表示不过滤
                if (condition.isIsdept() == true) {
                    if (CollectionUtils.isNotEmpty(deptIds)) {
                        boolean deptIsExist = false;//level4的部门是否匹配用户部门
                        for (Integer deptId : deptIds) {
                            if (deptId == subLevel.getDeptid()) {
                                deptIsExist = true;
                            }
                        }
                        if (!deptIsExist) isRemoveSubLevel = true;
                    }
                }

                if (isRemoveSubLevel) subLevelIterator.remove();
            }
        }
    }

    /**
     * 指定单元查询危险源
     *
     * @param id 单元ID
     * @return QueryOneUnitHazardResultDto
     * @author QuCheng Tech
     * @description 返回指定单元的危险源信息
     * @since 2024/11/6
     */
    public QueryOneUnitHazardResultDto getOneUnit(String id) throws QCPromptException {
        //1.查询条件有效性验证
        if (StringUtils.isBlank(id)) throw new QCPromptException("单元ID不能为空");

        //2.获取指定单元信息
        EhsUnitInfo unitInfo = unitInfoRepository.selectById(id);
        if (unitInfo == null) return null;

        //3.获取指定单元的危险源信息
        List<EhsHazardInfoDto> hazards = getByUnitId(id);

        //4.构建返回结果对象
        QueryOneUnitHazardResultDto result = new QueryOneUnitHazardResultDto();
        result.setUnitid(unitInfo.getUnitid());
        result.setUnitname(unitInfo.getUnitname());
        result.setUccd(unitInfo.getUccd());
        if (unitInfo.getIdtm() != null) result.setIdtm(DateUtil.getDateTimeString(unitInfo.getIdtm()));
        result.setIsconstruction(unitInfo.getIsconstruction());
        result.setGeneral1(unitInfo.getGeneral1() == null ? 0x0 : unitInfo.getGeneral1());
        result.setMajor1(unitInfo.getMajor1() == null ? 0x0 : unitInfo.getMajor1());
        result.setLevel11(unitInfo.getLevel11() == null ? 0x0 : unitInfo.getLevel11());
        result.setLevel12(unitInfo.getLevel12() == null ? 0x0 : unitInfo.getLevel12());
        result.setLevel13(unitInfo.getLevel13() == null ? 0x0 : unitInfo.getLevel13());
        result.setLevel14(unitInfo.getLevel14() == null ? 0x0 : unitInfo.getLevel14());
        result.setGeneral2(unitInfo.getGeneral2() == null ? 0x0 : unitInfo.getGeneral2());
        result.setMajor2(unitInfo.getMajor2() == null ? 0x0 : unitInfo.getMajor2());
        result.setLevel21(unitInfo.getLevel21() == null ? 0x0 : unitInfo.getLevel21());
        result.setLevel22(unitInfo.getLevel22() == null ? 0x0 : unitInfo.getLevel22());
        result.setLevel23(unitInfo.getLevel23() == null ? 0x0 : unitInfo.getLevel23());
        result.setLevel24(unitInfo.getLevel24() == null ? 0x0 : unitInfo.getLevel24());
        result.setHazards(hazards);
        return result;
    }

    /**
     * 获取指定单元的第一类危险源
     *
     * @param unitId 单元ID
     * @return List<EhsHazardInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/6
     */
    public List<EhsHazardInfoDto> getUnitHazards(String unitId) throws QCPromptException {
        if (StringUtils.isBlank(unitId)) throw new QCPromptException("单元ID不能为空");
        EhsUnitInfo unitInfo = unitInfoRepository.selectById(unitId);
        if (unitInfo == null) throw new QCPromptException("指定单元信息不存在");

        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsHazardInfo::getUnitid, unitId);
        wrapper.eq(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.HAZARD.getIndex());
        List<EhsHazardInfo> ens = repository.selectList(wrapper);

        if (ens != null && ens.size() > 0x0) {
            return EhsHazardInfoMapper.MAPPER.toDtoList(ens);
        }
        return null;
    }

    /**
     * 获取指定单元的隐患（第二类危险源）
     *
     * @param unitId 单元ID
     * @return List<EhsHazardInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/6
     */
    public List<EhsHazardInfoDto> getUnitHiddenTrouble(String unitId) throws QCPromptException {
        if (StringUtils.isBlank(unitId)) throw new QCPromptException("单元ID不能为空");
        EhsUnitInfo unitInfo = unitInfoRepository.selectById(unitId);
        if (unitInfo == null) throw new QCPromptException("指定单元信息不存在");

        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsHazardInfo::getUnitid, unitId);
        wrapper.eq(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.HIDDEN_TROUBLE.getIndex());
        List<EhsHazardInfo> ens = repository.selectList(wrapper);

        if (ens != null && ens.size() > 0x0) {
            return EhsHazardInfoMapper.MAPPER.toDtoList(ens);
        }
        return null;
    }

    /**
     * 获取指定单元指定危险源类别、项目、清单的危险源信息
     *
     * @param unitId       单元ID
     * @param categoryCode 所属类别代码
     * @param projectCode  所属项目代码
     * @param itemCode     所属清单代码
     * @return EhsHazardInfoDto
     * @author QuCheng Tech
     * @since 2024/11/21
     */
    public EhsHazardInfoDto getByUnitIdAndItemId(String unitId, String categoryCode, String projectCode, String itemCode) {
        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsHazardInfo::getUnitid, unitId)
                .eq(EhsHazardInfo::getCategorycode, categoryCode)
                .eq(EhsHazardInfo::getProjectcode, projectCode)
                .eq(EhsHazardInfo::getItemcode, itemCode);
        EhsHazardInfo en = repository.selectOne(wrapper);
        if (Objects.nonNull(en)) {
            return EhsHazardInfoMapper.MAPPER.toDto(en);
        }
        return null;
    }

    /**
     * 获取指定组织机构中的存在的所有危险源（可以指定第一类或第二类或者全部存在的危险源）
     *
     * @param orgCode              组织机构代码
     * @param hazardResultTypeFlag 危险源类别标记，为1表示只查询第一类危险源、为2表示只查询第二类危险源、为其他表示查询第一类和第二类危险源
     * @return java.util.List<qc.module.ehs.entity.EhsHazardInfo>
     * @author QuCheng Tech
     * @since 2024/12/13
     */
    public List<EhsHazardInfo> getOrgAllExistHazards(String orgCode, int hazardResultTypeFlag) throws QCPromptException {
        if (StringUtils.isBlank(orgCode)) throw new QCPromptException("组织机构代码不能为空");

        LambdaQueryWrapper<EhsHazardInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsHazardInfo::getOrgcode, orgCode);
        if (hazardResultTypeFlag == 0x1)//只查询第一类危险源
            wrapper.eq(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.HAZARD);
        else if (hazardResultTypeFlag == 0x2)//只查询第二类危险源
            wrapper.eq(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.HIDDEN_TROUBLE);
        else//查询第一类和第二类危险源
            wrapper.ne(EhsHazardInfo::getIdentificationresult, EhsHazardIndentificationResultTypeEnum.NOT_EXIST);

        return repository.selectList(wrapper);
    }
}
